﻿using FlyIL;
using FlyIL.Misc;
using FlyIL.Compiler;
using FlyRemote.Base;
using System.Collections.Generic;
using System.Linq;
using static FlyIL.OperandMaker;
using static FlyIL.AssemblerRegisters;
namespace FuckSp;



public class Detector
{

    /// <summary>
    /// 所有 sp入口 
    /// </summary>
    public List<SpEntry> spEntries = new List<SpEntry>();

    /// <summary>
    /// 所有的 handler ,序列化保存 
    /// </summary>
    public Dictionary<ulong, byte[]> handlers = new Dictionary<ulong, byte[]>();

    /// <summary>
    /// 所有 sp iat  
    /// </summary>
    public List<SpIat> SpIats = new List<SpIat>();

    /// <summary>
    /// 共享一个上下文
    /// 因为还原时  需要 地址统一
    /// </summary>
    public Context Vcontext;


    public ReadGroup ReadGroup;


    public Tag _checkVsp; 

    public Detector(ReadGroup group)
    {
        ReadGroup = group;
    }


    /// <summary>
    /// sp 的扫描只能 使用 类ida 的启发式扫描 ， 才能正确的  定位入口
    /// </summary>
    public void Detecter(bool is64, ulong address, IReader reader, IReport report)
    {

        Vcontext = new Context(is64, address);
        Vcontext.DumpPath = "C:\\Users\\lyo\\Desktop\\dump.txt";

        SpEntry entry = new(this);

        /// 如果在反汇编的过程中， 发现有其它的入中 ， 则直接 
        entry.Collect(is64, reader, report, address, 0);

    }


    /// <summary>
    /// 将收集并化简后的代码，转为原生汇编 
    /// </summary>
    /// <param name="baseAddress"></param>
    public byte[] Compile(ulong baseAddress, IReport report)
    {
        return Jit.Intel.Compile(Vcontext, baseAddress, report);

    }

    /// <summary>
    /// 检测 handler 的类型 
    /// </summary>
    /// <param name="handler"></param>
    /// <param name="node"></param>
    /// <returns></returns>
    internal static HandleType CheckHandle(Context handler, out Inst node)
    {
        node = null;


        bool read_vip = false;

        bool push_esi = false;

        for (var u = handler.Entry; u != null; u = handler.GetNextIfExist(u))
        {
            //if (u.Vip == 0x042888F2)
            //    ;

            if (!push_esi)
                push_esi = u.IsMatch(Opt.push, _regs_[R6D], null);

            if (!push_esi)
            {

                /// 如果是 mov esi, xxxx 或者 pop esi ,则是 跳转  
                var a = u.IsMatch(Opt.mov, _regs_[AssemblerRegisters.R6D], null);
                var b = u.IsMatch(Opt.pop, _regs_[AssemblerRegisters.R6D], null);

                if (!read_vip && (a || b))
                    return HandleType.jmp;
            }


            {

                /// 如果存在 push [esi] 或者 mov xxx , [esi] ,则可能是计算下一处 handler 
                var a = u.IsMatch(Opt.push, _dword_[AssemblerRegisters.R6D], null);
                var b = u.IsMatch(Opt.mov, _regs_[AssemblerRegisters.Any], _dword_[AssemblerRegisters.R6D]);
                if (!read_vip && a || b)
                    read_vip = true;

            }

            if (!read_vip && u.IsJxx)
            {
                node = u;

                /// 如果 有rep 指令, 则是 checkvsp , 否则是 jcc

                return handler.Codes.Any(o => o.HavePrefix) ? HandleType.checkVsp : HandleType.jcc;
            }
        }

        return HandleType.normal;
    }


}


